#include "analisador.h"

//**********************************************************************//
//**************************SINTATICO***********************************//

void cria_pilha()
{
	topo = NULL;
}

int pilha_vazia()
{
	return topo == NULL;
}

void empilha(int n)
{
	if (pilha_vazia())
	{
		topo = malloc(sizeof(*topo));
		topo->ant= NULL;
		topo->prox= NULL;
		topo->elemento = n;
	}
	else
	{
		pilha x = malloc(sizeof(*x));
		x->prox = topo->prox; //precisa ser assim?
		x->ant = topo;
		topo->prox = x; //precisa ser assim?
		topo = x;
		topo->elemento = n;
	}
}

char desempilha()
{
	pilha x = topo->ant;
	int aux = topo->elemento;

	free(topo);
	topo = x;
	topo->prox = x; //precisa ser assim?

	//return aux;
}

int reconhece_simbolo(char simbolo[30])
{

	if (strcmp(simbolo,"(") == 0)
		return ABRE_PAR;

	if (strcmp(simbolo,")") == 0)
		return FECHA_PAR;
		
	if (strcmp(simbolo,"{") == 0)
		return ABRE_CHAVE;
		
	if (strcmp(simbolo,"}") == 0)
		return FECHA_CHAVE;
		
	if (strcmp(simbolo,"=") == 0)
		return IGUAL;
		
	if (strcmp(simbolo,",") == 0)
		return VIRGULA;
		
	if (strcmp(simbolo,";") == 0)
		return PONTO_VIRGULA;
		
	if (strcmp(simbolo,"int") == 0)
		return INT;
		
	if (strcmp(simbolo,"char") == 0)
		return CHAR;
		
	if (strcmp(simbolo,"float") == 0)
		return FLOAT;
		
	if (strcmp(simbolo,"id") == 0)
		return ID;
		
	if (strcmp(simbolo,"str") == 0)
		return STR;
		
	if ((strcmp(simbolo,"Num") == 0) || (strcmp(simbolo,"num") == 0))
		return NUM;

	if (strcmp(simbolo,"main") == 0)
		return TERM_MAIN;
		
	if (strcmp(simbolo,"for") == 0)
		return TERM_FOR;
		
	if (strcmp(simbolo,"if") == 0)
		return TERM_IF;
		
	if (strcmp(simbolo,"else") == 0)
		return TERM_ELSE;
		
	if (strcmp(simbolo,"while") == 0)
		return TERM_WHILE;
		
	if (strcmp(simbolo,"return") == 0)
		return TERM_RETURN;
		
	if (strcmp(simbolo,"END") == 0)
		return VELHA;
		
	if (strcmp(simbolo,"PROG") == 0)
		return PROG;
		
	if (strcmp(simbolo,"MAIN") == 0)
		return MAIN;
		
	if (strcmp(simbolo,"IF") == 0)
		return IF;
		
	if (strcmp(simbolo,"FOR") == 0)
		return FOR;
		
	if (strcmp(simbolo,"WHILE") == 0)
		return WHILE;
		
	if (strcmp(simbolo,"RETURN") == 0)
		return RETURN;
		
	if (strcmp(simbolo,"PARAM") == 0)
		return PARAM;
		
	if (strcmp(simbolo,"TIPO") == 0)
		return TIPO;
		
	if (strcmp(simbolo,"FUNCOES") == 0)
		return FUNCOES;
		
	if (strcmp(simbolo,"FUNCAO") == 0)
		return FUNCAO;
		
	if (strcmp(simbolo,"DECL_VAR") == 0)
		return DECL_VAR;
		
	if (strcmp(simbolo,"DECL_PAR") == 0)
		return DECL_PAR;
		
	if (strcmp(simbolo,"CMDS") == 0)
		return CMDS;
		
	if (strcmp(simbolo,"EXP_REL") == 0)
		return EXP_REL;
		
	if (strcmp(simbolo,"EXP_MAT") == 0)
		return EXP_MAT;
		
	if (strcmp(simbolo,"OPER") == 0)
		return OPER;
	
	if (strcmp(simbolo,"ATRIB") == 0)
		return ATRIB;
		
	if (strcmp(simbolo,"CH_FUNC") == 0)
		return CH_FUNC;
		
	if (strcmp(simbolo,"OPERAN_MAT") == 0)
		return OPERAN_MAT;
		
	if (strcmp(simbolo,"op_relac") == 0)
		return OP_REL;
		
	if (strcmp(simbolo,"op_logic") == 0)
		return OP_LOG;

	if (strcmp(simbolo,"op_desloc") == 0)
		return OP_MAT;
		
	if (strcmp(simbolo,"op_aritm") == 0)
		return OP_MAT;

	if (strcmp(simbolo,"op_incre") == 0)
		return OP_INC;

	return -2;
}



limpa_buffer(char string[10], int n)
{
	int i;

	for(i=0;i<n;i++)
		string[i] = '\0';

}

int busca_reducao(int n, int reducao[TAM_REDUZ])
{
	FILE *arq;
	char caracter;
	char simbolo[30];
	int i, j, k;
		if  ((arq = fopen("reducoes","r")) == NULL)
		return -1;

	caracter = fgetc(arq);

	for(i = 1; i < n; i++)
	{

		while(caracter != '.')
			caracter = fgetc(arq);

		caracter = fgetc(arq);

	}
	j = 0;
	while(caracter != ':')
	{
		simbolo[j] = caracter;
		caracter = fgetc(arq);
		j++;
	}
	simbolo[j] = '\0';
	reducao[0] = reconhece_simbolo(simbolo);
	limpa_buffer(simbolo,30);
	caracter = fgetc(arq);

	k = 1;
	while(caracter != '.')
	{
		j = 0;
		limpa_buffer(simbolo,30);
		while(caracter != ':')
		{
			simbolo[j] = caracter;
			caracter = fgetc(arq);
			j++;
		}
		simbolo[j] = '\0';
		reducao[k] = reconhece_simbolo(simbolo);
		limpa_buffer(simbolo,30);
		caracter = fgetc(arq);
		k++;
	}
	reducao[k] = -1;
	return 0;
}

int carrega_slr(int slr[TAM_SLR][43])
{

	FILE *arq;

	int i, j, k;
	char caracter;
	char simbolo[10];
		if  ((arq = fopen("SLR1","r")) == NULL)
		return -1;

	caracter = fgetc(arq);

	for(i = 0; i < TAM_SLR-1; i++)
	{
		j = 1;
		while(caracter != '.')
		{
			k = 0;
			while(caracter != ':')
			{
				simbolo[k] = caracter;
				caracter = fgetc(arq);
				k++;
			}
			slr[i][j] = atoi(simbolo);
			limpa_buffer(simbolo,10);
			j++;
			caracter = fgetc(arq);
		}
		caracter = fgetc(arq);
	}
}

char *pega_simbolo(char token[100])
{
	int i = 1;
	int j = 0;
	char string[30];

	while(token[i] != ',')
	{
		string[j] = token[i];
		i++;
		j++;
	}
	if (token[i+1] == ',')
	{
		string[j] = token[i];
		string[j+1] = '\0';
	}
	else
		string[j] = '\0';

	limpa_buffer(token,100);
	strcpy(token,string);
	return token;		
}

int sintatico(char *token, int estado, int slr[TAM_SLR][N_SIMBOLOS]){

	int reduziu = 0;
	int reducao[TAM_REDUZ];
	char *aux_token = (char *) calloc (1,sizeof(char)*100);
	int simbolo;

	if(strcmp(token,"END") == 0)
		simbolo = reconhece_simbolo(token);
	else
		simbolo = reconhece_simbolo(pega_simbolo(token));

	int acao = slr[estado][simbolo];	

	//fprintf(stderr,"Estado %d Simbolo %d Acao %d\n",estado,simbolo,acao);
	empilha(estado);

	// Redução 		<<<======Arrumar Quando sai da reducao
	while (acao < 0)
	{
		acao = acao*(-1);
		if(busca_reducao(acao, reducao) == -1)
				return ERRO;

		int i = 1;
		while (reducao[i] != -1)	//topo->ant->elemento == reducao.direita[i])
		{
			reduziu = 1;
			desempilha();
			desempilha();
			i++;
		}
		acao = slr[topo->elemento][reducao[0]];
		//fprintf(stderr,"Estado %d Simbolo %d Acao %d\n",topo->elemento,reducao[0],acao);

			empilha(acao);
			empilha(reducao[0]);

		// Erro
		if (acao == ERRO)
			return ERRO;

		acao = slr[acao][simbolo];
		//fprintf(stderr,"*Simbolo %d Acao %d\n",simbolo,acao);
	}

	// Aceitação
	if (acao == ACEITA)
		return ACEITA;

	// Erro
	if (acao == ERRO)
		return ERRO;


	// Muda de estado
	if (acao > 0)
	{
		empilha(simbolo);
		return acao;
	}
}

